﻿using Microsoft.Xna.Framework;
using System;

namespace Serious
{
    public struct Rectangle2
    {
        public Vector2 Origin;
        public Vector2 Size;

        public Vector2 this[Vector2 pt]
        {
            get { return  Origin + pt * Size; }
            set { Origin = value - pt * Size; }
        }

        public Vector2 this[Single x, Single y]
        {
            get { return  this[new Vector2(x, y)]; }
            set { this[new Vector2(x, y)] = value; }
        }

        public Vector2 LowLow
        {
            get { return  this[new Vector2(0.0f, 0.0f)]; }
            set { this[new Vector2(0.0f, 0.0f)] = value; }
        }
        public Vector2 LowMid
        {
            get { return  this[new Vector2(0.0f, 0.5f)]; }
            set { this[new Vector2(0.0f, 0.5f)] = value; }
        }
        public Vector2 LowHi
        {
            get { return  this[new Vector2(0.0f, 1.0f)]; }
            set { this[new Vector2(0.0f, 1.0f)] = value; }
        }

        public Vector2 MidLow
        {
            get { return  this[new Vector2(0.5f, 0.0f)]; }
            set { this[new Vector2(0.5f, 0.0f)] = value; }
        }
        public Vector2 MidMid
        {
            get { return  this[new Vector2(0.5f, 0.5f)]; }
            set { this[new Vector2(0.5f, 0.5f)] = value; }
        }
        public Vector2 MidHi
        {
            get { return  this[new Vector2(0.5f, 1.0f)]; }
            set { this[new Vector2(0.5f, 0.0f)] = value; }
        }

        public Vector2 HiLow
        {
            get { return  this[new Vector2(1.0f, 0.0f)]; }
            set { this[new Vector2(1.0f, 0.0f)] = value; }
        }
        public Vector2 HiMid
        {
            get { return  this[new Vector2(1.0f, 0.5f)]; }
            set { this[new Vector2(1.0f, 0.5f)] = value; }
        }
        public Vector2 HiHi
        {
            get { return  this[new Vector2(1.0f, 1.0f)]; }
            set { this[new Vector2(1.0f, 1.0f)] = value; }
        }

        public Rectangle2(Vector2 origin, Vector2 size)
        {
            Origin = origin;
            Size = size;
        }
        public Rectangle2(Single originX, Single originY, Single sizeWidth, Single sizeHeight) :
            this(new Vector2(originX, originY), new Vector2(sizeWidth, sizeHeight))
        {
        }

        public static Rectangle2 FromPoints(Vector2 p1, Vector2 p2)
        {
            Vector2 pMin = Vector2.Min(p1, p2);
            Vector2 pMax = Vector2.Max(p1, p2);
            return new Rectangle2(pMin, pMax - pMin);
        }

        public Single Left
        {
            get { return  Origin.X; }
            set { Origin.X = value; }
        }
        public Single Right
        {
            get { return  Origin.X + Size.X; }
            set { Origin.X = value - Size.X; }
        }

        public Single Top
        {
            get { return  Origin.Y; }
            set { Origin.Y = value; }
        }
        public Single Bottom
        {
            get { return  Origin.Y + Size.Y; }
            set { Origin.X = value - Size.Y; }
        }

        public static bool Intersect(Rectangle2 r1, Rectangle2 r2)
        {
            return r1.Right > r2.Left &&
                   r1.Left < r2.Right &&
                   r1.Bottom > r2.Top &&
                   r1.Top < r2.Bottom;
        }

        public bool Contains(Vector2 point)
        {
            return point.X > Left && point.X < Right && point.Y > Top && point.Y < Bottom;
        }

        public void Translate(Vector2 offset)
        {
            Origin += offset;
        }
        
        public static Rectangle2 operator +(Rectangle2 rect, Vector2 offset)
        {
            rect.Translate(offset);
            return rect;
        }
        public static Rectangle2 operator -(Rectangle2 rect, Vector2 offset)
        {
            rect.Translate(-offset);
            return rect;
        }

        /**
         * relative to origin of entire euclidean plane
         * */
        public void Scale(Vector2 factor)
        {
            Origin *= factor;
            Size *= factor;
        }

        /**
         * relative to origin of entire euclidean plane
         * */
        public void Scale(Single factor)
        {
            Origin *= factor;
            Size *= factor;
        }

        public static Rectangle2 operator *(Rectangle2 rect, Vector2 factor)
        {
            rect.Scale(factor);
            return rect;
        }
        public static Rectangle2 operator *(Rectangle2 rect, Single factor)
        {
            rect.Scale(factor);
            return rect;
        }
        public static Rectangle2 operator /(Rectangle2 rect, Vector2 factor)
        {
            rect.Origin /= factor;
            rect.Size /= factor;
            return rect;
        }
        public static Rectangle2 operator /(Rectangle2 rect, Single factor)
        {
            rect.Origin /= factor;
            rect.Size /= factor;
            return rect;
        }
    }
}
